home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / VECTBAL2.ZIP / VECTBAL2.CPP < prev    next >
C/C++ Source or Header  |  1994-12-04  |  11KB  |  467 lines

  1. //////////////////////////////////
  2. // VECTOR BALLS 2               //
  3. // (c) 1994 by Bodies In Motion //
  4. // code - Tumblin               //
  5. // graphics - Rush              //
  6. //////////////////////////////////
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <math.h>
  11. #include <conio.h>
  12. #include <dos.h>
  13. #include <xlib_all.h>
  14.  
  15. // include the palette and bitmap data of the vector ball
  16. #include "vectbal2.h"
  17.  
  18. //──────────────────────── fixed point math code ─────────────────────────
  19.  
  20. typedef long Fixedpoint;
  21.  
  22. #define Int2Fixed(a)    (Fixedpoint)((Fixedpoint)(a) << 16)
  23. #define Fixed2Int(a)    (int)((a) >> 16)
  24. #define Float2Fixed(a)    ((Fixedpoint)((a) * 65536.0))
  25. #define Fixed2Float(a)    ((a) / 65536.0)
  26.  
  27. extern "C" {
  28.                          Fixedpoint FixedMul(Fixedpoint,Fixedpoint);
  29.                          Fixedpoint FixedDiv(Fixedpoint,Fixedpoint);
  30.                      };
  31.  
  32.  
  33. //──────────────────────── some helpful constants ────────────────────────
  34.  
  35. // maximum # of degrees for sin and cos tables
  36. #define MAXDEGREES 720
  37.  
  38. // distance from users eye to screen surface in pixels
  39. #define EYE_DISTANCE Int2Fixed(256)
  40.  
  41. // depth to push objects into the screen
  42. #define DEPTH Int2Fixed(1024)
  43.  
  44. // maximum number of balls an object can have
  45. #define MAXBALLS 100
  46.  
  47. //──────────────────────────── data structures ───────────────────────────
  48. //────────────────────────────────────────────────────────────────────────
  49.  
  50. char filename[80];
  51.  
  52. Fixedpoint cosine[MAXDEGREES];  // cosine lookup table
  53. Fixedpoint sine[MAXDEGREES];    // sine lookup table
  54.  
  55. typedef struct
  56. {
  57.     Fixedpoint ox,oy,oz;  // origional x,y,z coordinates of ball
  58.     Fixedpoint wx,wy,wz;  // working copy of x,y,z coordinates of ball
  59.     int sx,sy,sz;         // screen coordinates of ball
  60. } BallTYPE;
  61.  
  62. int NumOfBalls=0; // current number of defined balls in object
  63.  
  64. BallTYPE Ball[MAXBALLS];  // object containing MAXBALLS balls
  65. int SBall[MAXBALLS]; // indexes to ball structures (for qsorting)
  66.  
  67. int XAngle=0;  // degrees to rotate object around x axis
  68. int YAngle=0;  // degrees to rotate object around y axis
  69. int ZAngle=0;  // degrees to rotate object around z axis
  70.  
  71. // bounding erase box
  72. int EraseLeft;    // current frame
  73. int EraseTop;     // current frame
  74. int EraseRight;   // current frame
  75. int EraseBottom;  // current frame
  76. int EraseLeft1;   // from 1 frame ago
  77. int EraseTop1;    // from 1 frame ago
  78. int EraseRight1;  // from 1 frame ago
  79. int EraseBottom1; // from 1 frame ago
  80. int EraseLeft2;   // from 2 frames ago
  81. int EraseTop2;    // from 2 frames ago
  82. int EraseRight2;  // from 2 frames ago
  83. int EraseBottom2; // from 2 frames ago
  84.  
  85. unsigned char old_palette[768];
  86. unsigned char current_palette[768]={0};
  87.  
  88. //───────────────────────────── function prototypes ────────────────────────
  89.  
  90. void main(int argc,char *argv[]);
  91. void InitSinCosTables(void);
  92. void InitSortList(void);
  93. int LoadObject(char * filename);
  94. void UpdateBalls(void);
  95. int CompareBalls(const void *a, const void *b);
  96. void WaitVerticalRetrace(void);
  97. void FadeInPalette(unsigned char *,int);
  98. void FadeOutPalette(int);
  99. void GetPalette(unsigned char *);
  100. void SetPalette(unsigned char *);
  101. void FadeInOne64th(unsigned char *,unsigned char *);
  102. void FadeOutOne64th(unsigned char *);
  103.  
  104. //──────────────── code to create sin and cos lookup tables ──────────────
  105.  
  106. void InitSinCosTables(void)
  107. {
  108.     int i;
  109.     for(i=0; i<MAXDEGREES; i++)
  110.     {
  111.         cosine[i]=Float2Fixed(cos((float)i*360/MAXDEGREES * 3.14159265 / 180.0));
  112.         sine[i]  =Float2Fixed(sin((float)i*360/MAXDEGREES * 3.14159265 / 180.0));
  113.     }
  114. }
  115.  
  116. //──────────────────── initialize the sorted ball list ──────────────────────
  117.  
  118. void InitSortList(void)
  119. {
  120.     // point each element to an initial ball
  121.     for(int i=0; i<MAXBALLS; i++)
  122.     {
  123.         SBall[i]=i;
  124.     }
  125. }
  126.  
  127. //────────────────────────── compare balls (for qsort) ─────────────────────
  128.  
  129. int CompareBalls(const void *a, const void *b)
  130. {
  131.     if( Ball[*(int *)a].sz < Ball[*(int *)b].sz )
  132.     {
  133.         return -1;
  134.     }
  135.     else if( Ball[*(int *)a].sz > Ball[*(int *)b].sz )
  136.     {
  137.         return +1;
  138.     }
  139.     else
  140.     {
  141.         return 0;
  142.     }
  143. }
  144.  
  145. //──────────────────────── update vector ball object ─────────────────────
  146.  
  147. void UpdateBalls(void)
  148. {
  149.     int i;
  150.     Fixedpoint nx,ny,nz;
  151.     Fixedpoint sinxangle,cosxangle;
  152.     Fixedpoint sinyangle,cosyangle;
  153.     Fixedpoint sinzangle,coszangle;
  154.  
  155.     // initialize the bounding box to its extremes
  156.     EraseLeft=320;
  157.     EraseTop=240;
  158.     EraseRight=0;
  159.     EraseBottom=0;
  160.  
  161.     // get the sine and cosine angles to save time from table lookup
  162.     sinxangle=sine[XAngle];
  163.     cosxangle=cosine[XAngle];
  164.     sinyangle=sine[YAngle];
  165.     cosyangle=cosine[YAngle];
  166.     sinzangle=sine[ZAngle];
  167.     coszangle=cosine[ZAngle];
  168.  
  169.     // rotate the balls
  170.     for(i=0;i<NumOfBalls;i++)
  171.     {
  172.         // rotate around the x-axis
  173.         Ball[i].wz=FixedMul(Ball[i].oy,cosxangle) - FixedMul(Ball[i].oz,sinxangle);
  174.         Ball[i].wy=FixedMul(Ball[i].oy,sinxangle) + FixedMul(Ball[i].oz,cosxangle);
  175.         Ball[i].wx=Ball[i].ox;
  176.  
  177.         // rotate around the y-axis
  178.         nx=FixedMul(Ball[i].wx,cosyangle) - FixedMul(Ball[i].wz,sinyangle);
  179.         nz=FixedMul(Ball[i].wx,sinyangle) + FixedMul(Ball[i].wz,cosyangle);
  180.         Ball[i].wx=nx;
  181.         Ball[i].wz=nz;
  182.  
  183.         // rotate around the z-axis
  184.         nx=FixedMul(Ball[i].wx,coszangle) - FixedMul(Ball[i].wy,sinzangle);
  185.         ny=FixedMul(Ball[i].wx,sinzangle) + FixedMul(Ball[i].wy,coszangle);
  186.         Ball[i].wx=nx;
  187.         Ball[i].wy=ny;
  188.  
  189.         // project the 3-D coordinates to screen coordinates
  190.         Ball[i].sx=Fixed2Int(FixedMul(FixedDiv(Ball[i].wx,Ball[i].wz - DEPTH),EYE_DISTANCE)) + 160;
  191.         Ball[i].sy=Fixed2Int(FixedMul(FixedDiv(Ball[i].wy,Ball[i].wz - DEPTH),EYE_DISTANCE)) + 120;
  192.         Ball[i].sz=Fixed2Int(Ball[i].wz-DEPTH);
  193.  
  194.         // and while we're at it, find the bounding box for erasing balls
  195.         if(Ball[i].sx < EraseLeft)
  196.         {
  197.             EraseLeft=Ball[i].sx;
  198.         }
  199.         if(Ball[i].sy < EraseTop)
  200.         {
  201.             EraseTop=Ball[i].sy;
  202.         }
  203.         if(Ball[i].sx > EraseRight)
  204.         {
  205.             EraseRight=Ball[i].sx;
  206.         }
  207.         if(Ball[i].sy > EraseBottom)
  208.         {
  209.             EraseBottom=Ball[i].sy;
  210.         }
  211.     }
  212.  
  213.     // sort the balls according to their z coordinate
  214.     qsort((const void *)SBall,NumOfBalls,sizeof(SBall[0]),CompareBalls);
  215.  
  216.     // erase the balls from 2 frames ago (remember, we're double buffering)
  217.     x_rect_fill(EraseLeft2-12,EraseTop2-12,
  218.                             EraseRight2+16,EraseBottom2+16,
  219.                             HiddenPageOffs,0);
  220.  
  221.     // draw the new balls onto the screen
  222.     for(i=0; i<NumOfBalls; i++)
  223.     {
  224.         x_put_masked_pbm(Ball[SBall[i]].sx-12,Ball[SBall[i]].sy-12,
  225.                                          HiddenPageOffs,bitmap);
  226.     }
  227.  
  228.     // update the bounding boxes for this frame
  229.     EraseTop2=EraseTop1;
  230.     EraseLeft2=EraseLeft1;
  231.     EraseRight2=EraseRight1;
  232.     EraseBottom2=EraseBottom1;
  233.     EraseTop1=EraseTop;
  234.     EraseLeft1=EraseLeft;
  235.     EraseRight1=EraseRight;
  236.     EraseBottom1=EraseBottom;
  237. }
  238.  
  239. //────────── load a dot object for use as a vector ball object ───────────
  240.  
  241. int LoadObject(char *filename)
  242. {
  243.     int i,temp;
  244.     FILE *file;
  245.  
  246.     // open the file to read from it
  247.     if ((file = fopen(filename,"rb"))    == NULL)
  248.     {
  249.         printf("\n\nCannot open input file.\n");
  250.         return (0);
  251.     }
  252.     else
  253.     {
  254.         // okay file is ready to read data from it
  255.  
  256.         // read number of dots in file
  257.         fread(&NumOfBalls,sizeof(int),1,file);
  258.  
  259.         // read in all of the object's dots
  260.         for(i=0;i < NumOfBalls; i++)
  261.         {
  262.             fread(&temp,sizeof(int),1,file);
  263.             Ball[i].ox=Int2Fixed(temp);
  264.             fread(&temp,sizeof(int),1,file);
  265.             Ball[i].oy=Int2Fixed(temp);
  266.             fread(&temp,sizeof(int),1,file);
  267.             Ball[i].oz=Int2Fixed(temp);
  268.         }
  269.  
  270.         // we're finished, close the file
  271.         fclose(file);
  272.         return (1);
  273.     }
  274. }
  275.  
  276. //──────────────────────── palette fading code ───────────────────────────
  277.  
  278. void WaitVerticalRetrace(void)
  279. {
  280.     asm    mov dx,3dah
  281.  
  282.     top_of_retrace:
  283.     asm    in    al,dx
  284.     asm    and    al,08h
  285.     asm    jnz    top_of_retrace
  286.  
  287.     bottom_of_retrace:
  288.     asm    in    al,dx
  289.     asm    and    al,08h
  290.     asm    jz    bottom_of_retrace
  291. }
  292.  
  293. void GetPalette(unsigned char *palettebuffer)
  294. {
  295.     int i;
  296.  
  297.     for(i=0;i<256;i++)
  298.     {
  299.         outp(0x3c7,i);    // color number to get data from
  300.         palettebuffer[i*3]   = inp(0x3c9);    // red
  301.         palettebuffer[i*3+1] = inp(0x3c9);    // green
  302.         palettebuffer[i*3+2] = inp(0x3c9);    // blue
  303.     }
  304. }
  305.  
  306. void SetPalette(unsigned char *palettebuffer)
  307. {
  308.     int i;
  309.  
  310.     for(i=0;i<256;i++)
  311.     {
  312.         outp(0x3c8,i);    // color number to set
  313.         outp(0x3c9,palettebuffer[i*3]);        // red
  314.         outp(0x3c9,palettebuffer[i*3+1]);    // green
  315.         outp(0x3c9,palettebuffer[i*3+2]);    // blue
  316.     }
  317. }
  318.  
  319. void FadeInPalette(unsigned char *palettebuffer,int speed)
  320. {
  321.     int i,j,k;
  322.     unsigned char temppalette[768]={0};
  323.  
  324.     for(i=0;i<64;i++)
  325.     {
  326.         for(j=0;j<256;j++)
  327.         {
  328.             // do the red component
  329.             if(temppalette[j*3] < palettebuffer[j*3])
  330.             {
  331.                 temppalette[j*3]++;
  332.             }
  333.             // do the green component
  334.             if(temppalette[j*3+1] < palettebuffer[j*3+1])
  335.             {
  336.                 temppalette[j*3+1]++;
  337.             }
  338.             // do the blue component
  339.             if(temppalette[j*3+2] < palettebuffer[j*3+2])
  340.             {
  341.                 temppalette[j*3+2]++;
  342.             }
  343.         }
  344.         for(k=0;k<speed;k++)
  345.         {
  346.             WaitVerticalRetrace();
  347.         }
  348.         SetPalette(temppalette);
  349.     }
  350. }
  351.  
  352. void FadeOutPalette(int speed)
  353. {
  354.     int i,j,k;
  355.     unsigned char temppalette[768];
  356.  
  357.     GetPalette(temppalette);
  358.  
  359.     for(i=0;i<64;i++)
  360.     {
  361.         for(j=0;j<256;j++)
  362.         {
  363.             // do the red component
  364.             if(temppalette[j*3] > 0)
  365.             {
  366.                 temppalette[j*3]--;
  367.             }
  368.             // do the green component
  369.             if(temppalette[j*3+1] > 0)
  370.             {
  371.                 temppalette[j*3+1]--;
  372.             }
  373.             // do the blue component
  374.             if(temppalette[j*3+2] > 0)
  375.             {
  376.                 temppalette[j*3+2]--;
  377.             }
  378.         }
  379.         for(k=0;k<speed;k++)
  380.         {
  381.             WaitVerticalRetrace();
  382.         }
  383.         SetPalette(temppalette);
  384.     }
  385. }
  386.  
  387. //───────────────────────────── main program ─────────────────────────────
  388.  
  389. void main(int argc,char *argv[])
  390. {
  391.  
  392.     if(argc<=1)
  393.     {
  394.         printf("┌─────────────────┐\n");
  395.         printf("│ VECTOR BALLS II │\n");
  396.         printf("└─────────────────┘\n");
  397.         printf("Syntax: VECTBAL2 filename.DOT\n\n");
  398.         exit(1);
  399.     }
  400.  
  401.     if(LoadObject(argv[1])==0)
  402.     {
  403.         printf("Error: could not find that file.\n");
  404.         exit(1);
  405.     }
  406.  
  407.  
  408.     InitSinCosTables();
  409.     InitSortList();
  410.     GetPalette(old_palette);
  411.  
  412.     SetPalette(current_palette);
  413.     _setcursortype(_NOCURSOR);
  414.     clrscr();
  415.     printf("\n\n\n\n\n\n\n\n");
  416.     printf("                          ┌──────────────────────────────┐\n");
  417.     printf("                          │        VECTOR BALLS II       │\n");
  418.     printf("                          │ (c) 1994 by Bodies In Motion │\n");
  419.     printf("                          │       code     - Tumblin     │\n");
  420.     printf("                          │       graphics - Rush        │\n");
  421.     printf("                          └──────────────────────────────┘\n\n\n");
  422.  
  423.     FadeInPalette(old_palette,2);
  424.     delay(1000);
  425.     FadeOutPalette(2);
  426.  
  427.     x_set_mode(X_MODE_320x240,320);
  428.     x_set_doublebuffer(240);
  429.     x_put_pal_raw(palette,256,0);
  430.     delay(1000);
  431.  
  432.     do
  433.     {
  434.         XAngle+=6;
  435.         if(XAngle >= MAXDEGREES)
  436.         {
  437.             XAngle -= MAXDEGREES;
  438.         }
  439.         YAngle+=4;
  440.         if(YAngle >= MAXDEGREES)
  441.         {
  442.             YAngle -= MAXDEGREES;
  443.         }
  444.         ZAngle+=3;
  445.         if(ZAngle >= MAXDEGREES)
  446.         {
  447.             ZAngle -= MAXDEGREES;
  448.         }
  449.  
  450.         UpdateBalls();
  451.         x_page_flip(0,0);
  452.     } while(!kbhit());
  453.  
  454.     getch();
  455.  
  456.     x_text_mode();
  457.     for(int i=0;i<256;i++)
  458.     {
  459.         current_palette[i]=0;
  460.     }
  461.     SetPalette(current_palette);
  462.     printf("We hope this has been a 'moving' experience.");
  463.     delay(1000);
  464.     FadeInPalette(old_palette,1);
  465.     _setcursortype(_NORMALCURSOR);
  466. }
  467.